#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>       
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include "YUVConversion.h"


static long U[256], V[256], Y1[256], Y2[256]; 
#ifndef MAX  
#define MAX(a, b) ((a) > (b) ? (a) : (b))  
#endif  
#ifndef MIN  
#define MIN(a, b) ((a) < (b) ? (a) : (b))  
#endif  

static long int crv_tab[256];     
static long int cbu_tab[256];     
static long int cgu_tab[256];     
static long int cgv_tab[256];     
static long int tab_76309[256];   
static unsigned char clp[1024];   //for clip in CCIR601   

/*转换查询表的生成函数*/

void init_yuv420p_table()   
{     
    long int crv,cbu,cgu,cgv;     
    int i,ind;        
    static int init = 0;  
  
    if (init == 1) return;  
  
    crv = 104597; cbu = 132201;  /* fra matrise i global.h */     
    cgu = 25675;  cgv = 53279;     
     
    for (i = 0; i < 256; i++)      
    {     
        crv_tab[i] = (i-128) * crv;     
        cbu_tab[i] = (i-128) * cbu;     
        cgu_tab[i] = (i-128) * cgu;     
        cgv_tab[i] = (i-128) * cgv;     
        tab_76309[i] = 76309*(i-16);     
    }     
     
    for (i = 0; i < 384; i++)     
        clp[i] = 0;     
    ind = 384;     
    for (i = 0;i < 256; i++)     
        clp[ind++] = i;     
    ind = 640;     
    for (i = 0;i < 384; i++)     
        clp[ind++] = 255;  
  
    init = 1;  
}  

/*
 * 函数名称 : init_yuv422p_table
 * 函数介绍 : 将FMT_YUYV,FMT_YVYU,FMT_UYVY,FMT_VYUY转换成rgb24格式
 * 参数介绍 : 生成查询表格
 */  
void init_yuv422p_table(void)  
{  
    int i;  
    static int init = 0;  
    if (init == 1) return;  
    // Initialize table  
    for (i = 0; i < 256; i++)  
    {   
        V[i]  = 15938 * i - 2221300;  
        U[i]  = 20238 * i - 2771300;  
        Y1[i] = 11644 * i;  
        Y2[i] = 19837 * i - 311710;  
    }  
  
    init = 1;  
} 


/*
 * 函数名称 : yuv420sp_to_rgb24
 * 函数介绍 : 将FMT_NV12,FMT_NV21转换成rgb24格式，   sp == planar == YUV分开存储
 * 参数介绍 : 生成查询表格
 */
void yuv420sp_to_rgb24(int type, unsigned char* yuvbuffer,unsigned char* rgbbuffer, int width,int height)     
{  
    int y1, y2, u, v;      
    unsigned char *py1, *py2;     
    int i, j, c1, c2, c3, c4;     
    unsigned char *d1, *d2;     
    unsigned char *src_u;  
    static int init_yuv420p = 0;  
  
    src_u = yuvbuffer + width * height;   // u  
  
    py1 = yuvbuffer;   // y  
    py2 = py1 + width;     
    d1 = rgbbuffer;     
    d2 = d1 + 3 * width;     
  
    init_yuv420p_table();  
  
    for (j = 0; j < height; j += 2)      
    {      
        for (i = 0; i < width; i += 2)      
        {  
            if (type ==  FMT_NV12)  
            {  
                u = *src_u++;     
                v = *src_u++;      // v紧跟u，在u的下一个位置  
            }  
            if (type == FMT_NV21)  
            {  
                v = *src_u++;     
                u = *src_u++;      // u紧跟v，在v的下一个位置  
            }  
  
            c1 = crv_tab[v];     
            c2 = cgu_tab[u];     
            c3 = cgv_tab[v];     
            c4 = cbu_tab[u];     
  
            //up-left     
            y1 = tab_76309[*py1++];      
            *d1++ = clp[384+((y1 + c1)>>16)];       
            *d1++ = clp[384+((y1 - c2 - c3)>>16)];     
            *d1++ = clp[384+((y1 + c4)>>16)];     
  
            //down-left     
            y2 = tab_76309[*py2++];     
            *d2++ = clp[384+((y2 + c1)>>16)];       
            *d2++ = clp[384+((y2 - c2 - c3)>>16)];     
            *d2++ = clp[384+((y2 + c4)>>16)];     
  
            //up-right     
            y1 = tab_76309[*py1++];     
            *d1++ = clp[384+((y1 + c1)>>16)];       
            *d1++ = clp[384+((y1 - c2 - c3)>>16)];     
            *d1++ = clp[384+((y1 + c4)>>16)];     
  
            //down-right     
            y2 = tab_76309[*py2++];     
            *d2++ = clp[384+((y2 + c1)>>16)];       
            *d2++ = clp[384+((y2 - c2 - c3)>>16)];     
            *d2++ = clp[384+((y2 + c4)>>16)];     
        }  
        d1  += 3*width;  
        d2  += 3*width;  
        py1 += width;  
        py2 += width;  
    }  
}  

/*
 * 函数名称 : yuv422packed_to_rgb24
 * 函数介绍 : 将FMT_YUYV,FMT_YVYU,FMT_UYVY,FMT_VYUY转换成rgb24格式,  packed:YUV交错排放
 * 参数介绍 : typr : YUV422的格式
 *          yuv422p : YUV422的数据字节
 *          rgb : 生成的RGB数据字节
 *          width,height : 图片的宽高
 */
void yuv422packed_to_rgb24(int type, unsigned char* yuv422p, unsigned char* rgb, int width, int height)  
{  
    int y, cb, cr;  
    int r, g, b;  
    int i = 0;  
    unsigned char* p;  
    unsigned char* p_rgb;  
  
    p = yuv422p;  
  
    p_rgb = rgb;  
  
    init_yuv422p_table();  
  
    for (i = 0; i < width * height / 2; i++)  
    {  
        switch(type)  
        {  
        case FMT_YUYV:  
            y  = p[0];  
            cb = p[1];  
            cr = p[3];  
            break;  
        case FMT_YVYU:  
            y  = p[0];  
            cr = p[1];  
            cb = p[3];  
            break;  
        case FMT_UYVY:  
            cb = p[0];  
            y  = p[1];  
            cr = p[2];  
            break;  
        case FMT_VYUY:  
            cr = p[0];  
            y  = p[1];  
            cb = p[2];  
            break;  
        default:  
            break;  
        }  
  
        r = MAX (0, MIN (255, (V[cr] + Y1[y])/10000));   //R value  
        b = MAX (0, MIN (255, (U[cb] + Y1[y])/10000));   //B value  
        g = MAX (0, MIN (255, (Y2[y] - 5094*(r) - 1942*(b))/10000)); //G value  
  
        // 此处可调整RGB排序，BMP图片排序为BGR  
        // 默认排序为：RGB  
        p_rgb[0] = r;  
        p_rgb[1] = g;  
        p_rgb[2] = b;  
  
        switch(type)  
        {  
        case FMT_YUYV:  
        case FMT_YVYU:  
            y = p[2];  
            break;  
        case FMT_UYVY:  
        case FMT_VYUY:  
            y = p[3];  
            break;  
        default:  
            break;  
        }  
  
        r = MAX (0, MIN (255, (V[cr] + Y1[y])/10000));   //R value  
        b = MAX (0, MIN (255, (U[cb] + Y1[y])/10000));   //B value  
        g = MAX (0, MIN (255, (Y2[y] - 5094*(r) - 1942*(b))/10000)); //G value  
  
        p_rgb[3] = r;  
        p_rgb[4] = g;  
        p_rgb[5] = b;  
  
        p += 4;  
        p_rgb += 6;  
    }  
}  


